package com.hudson.core.concurrent;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class AsyncUtil {
    private static final ConcurrentHashMap<Long, AsyncEntry> asyncMap = new ConcurrentHashMap<>();
    private static final long FAIL_TIME = 5000;
    public static ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(
            1,
            (r) -> {
                Thread t = new Thread(r);
                t.setName("AsyncUtil-Cleaner");
                t.setDaemon(true);
                return t;
            });

    static {
        scheduledThreadPoolExecutor.scheduleWithFixedDelay(() -> {
            try {
                Iterator<Map.Entry<Long, AsyncEntry>> iterator = asyncMap.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map.Entry<Long, AsyncEntry> entry = iterator.next();
                    AsyncEntry asyncEntry = entry.getValue();
                    if (System.currentTimeMillis() - asyncEntry.createTime > FAIL_TIME) {
                        iterator.remove(); // 已超时，移除
                    }
                }
            } catch (Exception e) {
                // log exception
            }
        }, 0, 2, TimeUnit.SECONDS);
    }

    /**
     * 添加一個鍵值對到map中
     *
     * @param key 健
     */
    public static CompletableFuture<Boolean> sync(long key) {
        CompletableFuture<Boolean> future = new CompletableFuture<>();
        asyncMap.put(key, new AsyncEntry(future));
        return future;
    }


    /**
     * 添加一個鍵值對到map中
     *
     * @param key      健
     * @param callBack 回調
     */
    public static void async(long key, CallBack callBack) {
        asyncMap.put(key, new AsyncEntry(callBack));
    }

    /**
     * 移除指定的鍵值對
     *
     * @param key 健
     */
    public static void remove(long key) {
        AsyncEntry asyncEntry = asyncMap.remove(key); // 真正移除 key
        if (asyncEntry == null) {
            return; // 防止空指针
        }
        asyncEntry.complete();
    }

    static class AsyncEntry {
        private CompletableFuture<Boolean> future;
        private CallBack callBack;
        private long createTime;

        private AsyncEntry(CompletableFuture<Boolean> future) {
            this.future = future;
            this.callBack = null;
            this.createTime = System.currentTimeMillis();
        }

        private AsyncEntry(CallBack callBack) {
            this.future = null;
            this.callBack = callBack;
            this.createTime = System.currentTimeMillis();
        }

        public CallBack getCallBack() {
            return callBack;
        }

        public void setCallBack(CallBack callBack) {
            this.callBack = callBack;
        }

        public CompletableFuture<Boolean> getFuture() {
            return future;
        }

        public void setFuture(CompletableFuture<Boolean> future) {
            this.future = future;
        }

        public void complete() {
            if (future != null && !future.isDone()) {
                future.complete(true);
            } else if (callBack != null) {
                callBack.onSuccess();
            }
        }

        public long getCreateTime() {
            return createTime;
        }

        public void setCreateTime(long createTime) {
            this.createTime = createTime;
        }
    }
}
